package com.qdxht.dispenser.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import androidx.annotation.Nullable;

import com.hjq.toast.ToastUtils;
import com.qdxht.dispenser.utils.ConfigUtil;
import com.vi.vioserial.COMSerial;
import com.vi.vioserial.listener.OnComDataListener;
import com.qdxht.dispenser.utils.SerialProtocolUtil;
import com.qdxht.dispenser.utils.SerialProtocolUtil.ProtocolResult;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import timber.log.Timber;
import android.os.Handler;

/**
 * 串口通信服务
 * 封装了串口设备的扫描、连接、数据收发等功能
 */
public class SerialPortService extends Service {
    
    private static final String TAG = "SerialPortService";
    
    // 当前连接的串口路径
    private volatile String currentPortPath;
    // 当前设备的地址
    private byte currentDeviceAddress = 0;
    // 串口波特率
    private int baudRate = 9600;
    
    // 数据监听器列表，使用线程安全的集合
    private final List<OnSerialDataListener> dataListeners = new CopyOnWriteArrayList<>();
    // 状态监听器列表
    private final List<OnSerialStatusListener> statusListeners = new CopyOnWriteArrayList<>();
    
    // Service的Binder
    private final SerialPortBinder binder = new SerialPortBinder();

    // 设备无响应超时时长：10s
    private static final long TIME_OUT_MILLIS = 10 * 1000;

    @Override
    public void onCreate() {
        super.onCreate();
        Timber.tag(TAG).i("SerialPortService创建 this:%s",this);
        
        // 初始化串口监听
        initSerialListener();
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }
    
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Timber.tag(TAG).i("SerialPortService绑定 this:%s",this);
        return binder;
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        Timber.tag(TAG).i("SerialPortService销毁 this:%s",this);
        
        // 关闭所有串口连接
        disconnectAll();
        
        // 清理监听器
        dataListeners.clear();
        statusListeners.clear();
    }
    
    /**
     * 初始化串口监听器
     */
    private void initSerialListener() {
        COMSerial.instance().addDataListener(new OnComDataListener() {
            @Override
            public void comDataBack(String com, String hexData) {
                Timber.tag(TAG).d("收到串口数据: %s, %s", com, hexData);
                
                // 解析协议数据
                ProtocolResult result = SerialProtocolUtil.parseResponse(hexData);
                
                // 通知所有监听器
                for (OnSerialDataListener listener : dataListeners) {
                    listener.onDataReceived(com, hexData, result);
                }
            }
        });
    }

    OnComDataListener onComDataListener;
    /**
     * 扫描并连接ttyS开头的串口设备
     * 会尝试查找合适的设备地址
     * 
     * @return 是否找到并连接了设备
     */
    public void scanAndConnectPort(OnSerialFindListener listener) {
        Timber.tag(TAG).i("开始扫描串口设备");
        // 先断开可能存在的连接
        disconnectAll();
        
        // 获取所有ttyS串口设备
        List<String> serialPorts = findAllTtySPorts();
        if (serialPorts.isEmpty()) {
            Timber.tag(TAG).w("未找到ttyS串口设备");
            notifyStatusChanged(SerialStatus.NO_DEVICE_FOUND);
            return ;
        }
        onComDataListener = new OnComDataListener() {
            @Override
            public void comDataBack(String com, String hexData) {
                currentPortPath = com;
                currentDeviceAddress = (byte) Short.parseShort(hexData.substring(4, 6), 16);
                Timber.tag(TAG).i("扫描到可用串口: %s, 地址: %02X  this:%s", currentPortPath, currentDeviceAddress, SerialPortService.this);
                notifyStatusChanged(SerialStatus.CONNECTED);
                if(listener != null){
                    listener.onFind(currentPortPath, currentDeviceAddress);
                }
                COMSerial.instance().removeDataListener(onComDataListener);
                onComDataListener = null;
            }
        };
        COMSerial.instance().addDataListener(onComDataListener);

        // 发送命令获取剩余袋子测试命令
        String data = SerialProtocolUtil.buildFrame(0,SerialProtocolUtil.CMD_READ_CONFIG,05,"");
        for (String path : serialPorts) {
            if(!path.contains("ttyS")){
                continue;
            }
//            Timber.tag(TAG).i("找到串口："+path);
            int openStatus = COMSerial.instance().addCOM(path, 9600);
            Timber.tag(TAG).i("打开状态："+openStatus);
//            if(openStatus == 0){
//                COMSerial.instance().sendHex(path, data);
//                Timber.tag(TAG).i("发送命令："+data);
//            }
            try {
//                Timber.tag(TAG).i("发送命令0："+data);
                COMSerial.instance().sendHex(path, data);
                Timber.tag(TAG).i("发送命令：%s", data);
                Thread.sleep(200);
            } catch (Exception e) {
                Timber.tag(TAG).i("发送命令异常：%s", e.getMessage());
//                throw new RuntimeException(e);
            }
        }
        // 循环尝试每个串口
//        for (String portPath : serialPorts) {
//            Timber.tag(TAG).i("尝试连接串口: %s, 波特率: %d", portPath, baudRate);
//
//            // 打开串口
//            int openStatus = COMSerial.instance().addCOM(portPath, baudRate);
//            if (openStatus != 0) {
//                Timber.tag(TAG).e("打开串口失败: %s, 状态: %d", portPath, openStatus);
//                continue;
//            }
//
//            // 循环测试地址00~0F
//            boolean deviceFound = false;
//            for (int address = 0; address <= 0x0F; address++) {
//                Timber.tag(TAG).d("测试地址: %02X", address);
//
//                // 发送读配置参数命令
//                String command = SerialProtocolUtil.buildFrame(address, SerialProtocolUtil.CMD_READ_CONFIG, 5, "");
//                COMSerial.instance().sendHex(portPath, command);
//
//                // 等待短暂时间检查响应
//                try {
//                    Thread.sleep(100);
//                } catch (InterruptedException e) {
//                    Timber.tag(TAG).e(e, "线程中断");
//                }
//
//                // 如果当前端口已找到设备，跳出地址测试循环
//                if (currentPortPath != null) {
//                    currentDeviceAddress = (byte) address;
//                    deviceFound = true;
//                    break;
//                }
//            }
//
//            // 如果当前串口没有找到设备，关闭它
//            if (!deviceFound && COMSerial.instance().isOpen(portPath)) {
//                COMSerial.instance().close(portPath);
//            }
//
//            // 如果找到了设备，退出串口循环
//            if (deviceFound) {
//                Timber.tag(TAG).i("成功连接串口: %s, 地址: %02X", currentPortPath, currentDeviceAddress);
//                notifyStatusChanged(SerialStatus.CONNECTED);
//                return true;
//            }
//        }
    }
    
    /**
     * 获取所有ttyS开头的串口设备路径
     */
    private List<String> findAllTtySPorts() {
        List<String> ttySPorts = new ArrayList<>();
        
        android.serialport.SerialPortFinder finder = new android.serialport.SerialPortFinder();
        String[] allPorts = finder.getAllDevicesPath();
        
        if (allPorts != null && allPorts.length > 0) {
            for (String port : allPorts) {
                if (port.contains("ttyS")) {
                    ttySPorts.add(port);
                }
            }
        }
        
        return ttySPorts;
    }
    
    /**
     * 断开所有串口连接
     */
    public void disconnectAll() {
//        List<String> openPorts = COMSerial.instance().getOpenedComList();
//        for (String port : openPorts) {
//            if (COMSerial.instance().isOpen(port)) {
//                COMSerial.instance().close(port);
//                Timber.tag(TAG).d("关闭串口: %s", port);
//            }
//        }
        Timber.tag(TAG).i("断开所有串口连接.currentPortPath: %s this:%s", currentPortPath, this);
        currentPortPath = null;
        notifyStatusChanged(SerialStatus.DISCONNECTED);
    }
    
    /**
     * 断开当前串口连接
     */
    public void disconnect() {
        if (currentPortPath != null && COMSerial.instance().isOpen(currentPortPath)) {
            COMSerial.instance().close(currentPortPath);
            Timber.tag(TAG).d("关闭串口: %s", currentPortPath);
            currentPortPath = null;
            notifyStatusChanged(SerialStatus.DISCONNECTED);
        }
    }
    
    /**
     * 连接到指定串口
     * 
     * @param port 串口路径
     * @param baudRate 波特率
     * @return 是否连接成功
     */
    public boolean connect(String port, int baudRate) {
        if (port == null || port.isEmpty()) {
            return false;
        }
        
        // 先断开当前连接
        disconnect();
        
        // 更新波特率
        this.baudRate = baudRate;
        
        // 连接新串口
        int status = COMSerial.instance().addCOM(port, baudRate);
        if (status == 0) {
            currentPortPath = port;
            notifyStatusChanged(SerialStatus.CONNECTED);
            return true;
        } else {
            Timber.tag(TAG).e("连接串口失败: %s, 状态: %d", port, status);
            notifyStatusChanged(SerialStatus.CONNECTION_FAILED);
            return false;
        }
    }
    
    /**
     * 发送读传感器状态命令
     * 
     * @param sensorType 传感器类型
     * @return 是否发送成功
     */
    public boolean sendReadSensor(int sensorType) {
        if (currentPortPath == null) {
            Timber.tag(TAG).e("未连接串口，无法发送命令。 this:%s", this);
            return false;
        }
        
        return SerialProtocolUtil.sendReadSensor(currentPortPath, currentDeviceAddress, sensorType);
    }
    
    /**
     * 发送写配置参数命令
     * 
     * @param configType 配置类型
     * @param data 配置数据
     * @return 是否发送成功
     */
    public boolean sendWriteConfig(int configType, String data) {
        if (currentPortPath == null) {
            Timber.tag(TAG).e("未连接串口，无法发送命令。 this:%s", this);
            return false;
        }
        
        return SerialProtocolUtil.sendWriteConfig(currentPortPath, currentDeviceAddress, configType, data);
    }
    
    /**
     * 发送读配置参数命令
     * 
     * @param configType 配置类型
     * @return 是否发送成功
     */
    public boolean sendReadConfig(int configType) {
        if (currentPortPath == null) {
            Timber.tag(TAG).e("未连接串口，无法发送命令。 this:%s", this);
            return false;
        }
        
        return SerialProtocolUtil.sendReadConfig(currentPortPath, currentDeviceAddress, configType);
    }

    /**
     * 发送发袋命令
     * @return 是否发送成功
     */
    public boolean sendDispense() {
        String lengthValue = ConfigUtil.getRollingDistance() + "";
        int decValue = Integer.parseInt(lengthValue);
        String hexLengthValue = Integer.toHexString(decValue);
        // 确保是偶数个字符
        if (hexLengthValue.length() % 2 != 0) {
            hexLengthValue = "0" + hexLengthValue;
        }
        return sendDispense(0x02, hexLengthValue);
    }

    /**
     * 发送发袋命令
     * 
     * @param dispenserType 发袋类型
     * @param length 长度值
     * @return 是否发送成功
     */
    public boolean sendDispense(int dispenserType, String length) {
        if (currentPortPath == null) {
            Timber.tag(TAG).e("未连接串口，无法发送命令。 this:%s", this);
            return false;
        }
        
        return SerialProtocolUtil.sendDispense(currentPortPath, currentDeviceAddress, dispenserType, length);
    }
    
    /**
     * 发送错误恢复命令
     * 
     * @param errorType 错误类型
     * @return 是否发送成功
     */
    public boolean sendErrorRecovery(int errorType) {
        if (currentPortPath == null) {
            Timber.tag(TAG).e("未连接串口，无法发送命令。 this:%s", this);
            return false;
        }
        
        return SerialProtocolUtil.sendErrorRecovery(currentPortPath, currentDeviceAddress, errorType);
    }
    
    /**
     * 添加数据监听器
     */
    public void addDataListener(OnSerialDataListener listener) {
        if (listener != null && !dataListeners.contains(listener)) {
            dataListeners.add(listener);
        }
    }
    
    /**
     * 移除数据监听器
     */
    public void removeDataListener(OnSerialDataListener listener) {
        dataListeners.remove(listener);
    }
    
    /**
     * 添加状态监听器
     */
    public void addStatusListener(OnSerialStatusListener listener) {
        if (listener != null && !statusListeners.contains(listener)) {
            statusListeners.add(listener);
        }
    }
    
    /**
     * 移除状态监听器
     */
    public void removeStatusListener(OnSerialStatusListener listener) {
        statusListeners.remove(listener);
    }
    
    /**
     * 通知状态变化
     */
    private void notifyStatusChanged(SerialStatus status) {
        for (OnSerialStatusListener listener : statusListeners) {
            listener.onStatusChanged(status);
        }
    }
    
    /**
     * 获取当前连接的串口路径
     */
    public String getCurrentPortPath() {
        return currentPortPath;
    }
    
    /**
     * 获取当前设备地址
     */
    public byte getCurrentDeviceAddress() {
        return currentDeviceAddress;
    }
    
    /**
     * 设置设备地址
     */
    public void setCurrentDeviceAddress(byte address) {
        this.currentDeviceAddress = address;
    }
    
    /**
     * 获取当前波特率
     */
    public int getBaudRate() {
        return baudRate;
    }
    
    /**
     * 串口状态枚举
     */
    public enum SerialStatus {
        DISCONNECTED("已断开连接"),
        CONNECTING("正在连接..."),
        CONNECTED("已连接"),
        CONNECTION_FAILED("连接失败"),
        NO_DEVICE_FOUND("未找到设备");
        
        private final String description;
        
        SerialStatus(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    /**
     * 串口数据监听接口
     */
    public interface OnSerialDataListener {
        /**
         * 当接收到数据时回调
         * 
         * @param port 串口路径
         * @param hexData 原始十六进制数据
         * @param result 解析后的协议结果
         */
        void onDataReceived(String port, String hexData, ProtocolResult result);
    }
    
    /**
     * 串口状态监听接口
     */
    public interface OnSerialStatusListener {
        /**
         * 当串口状态改变时回调
         * 
         * @param status 新状态
         */
        void onStatusChanged(SerialStatus status);
    }
    
    /**
     * Service的Binder，提供访问Service方法的接口
     */
    public class SerialPortBinder extends Binder {
        public SerialPortService getService() {
            return SerialPortService.this;
        }
    }

    /**
     * 串口数据监听接口
     */
    public interface OnSerialFindListener {
        /**
         * 当接收到数据时回调
         *
         * @param port 串口路径
         * @param addr 地址
         */
        void onFind(String port, byte addr);
    }

    public interface CommandCallback {
        void onResult(boolean success, String msg, ProtocolResult result);
    }

    /**
     * 发送发袋命令并等待设备响应（带超时）
     */
    public void sendDispenseWithResult(int dispenserType, String length, CommandCallback callback) {
        boolean sendOk = sendDispense(dispenserType, length);
        if (!sendOk) {
            if (callback != null) callback.onResult(false, "串口服务异常，命令发送失败", null);
            return;
        }
        final Handler handler = new Handler(android.os.Looper.getMainLooper());
        SerialPortService.OnSerialDataListener listener = new SerialPortService.OnSerialDataListener() {
            @Override
            public void onDataReceived(String port, String hexData, ProtocolResult result) {
                if (result != null && result.statusType == SerialProtocolUtil.STATUS_DISPENSE) {
                    removeDataListener(this);
                    handler.removeCallbacksAndMessages(null);
                    if (callback != null) {
                        callback.onResult(result.isSuccess(), result.getMessage(), result);
                    }
                }
            }
        };
        addDataListener(listener);
        handler.postDelayed(() -> {
            removeDataListener(listener);
            if (callback != null) callback.onResult(false, "设备无响应超时", null);
        }, TIME_OUT_MILLIS);
    }

    /**
     * 发送发袋命令并等待设备响应（带超时）
     */
    public void sendDispenseWithResult(CommandCallback callback) {
        boolean sendOk = sendDispense();
        if (!sendOk) {
            if (callback != null) callback.onResult(false, "串口服务异常，命令发送失败", null);
            return;
        }
        final Handler handler = new Handler(android.os.Looper.getMainLooper());
        SerialPortService.OnSerialDataListener listener = new SerialPortService.OnSerialDataListener() {
            @Override
            public void onDataReceived(String port, String hexData, ProtocolResult result) {
                if (result != null && result.statusType == SerialProtocolUtil.STATUS_DISPENSE) {
                    removeDataListener(this);
                    handler.removeCallbacksAndMessages(null);
                    if (callback != null) {
                        callback.onResult(result.isSuccess(), result.getMessage(), result);
                    }
                }
            }
        };
        addDataListener(listener);
        handler.postDelayed(() -> {
            removeDataListener(listener);
            if (callback != null) callback.onResult(false, "设备无响应超时", null);
        }, TIME_OUT_MILLIS);
    }

    /**
     * 发送读传感器命令并等待响应
     */
    public void sendReadSensorWithResult(int sensorType, CommandCallback callback) {
        boolean sendOk = sendReadSensor(sensorType);
        if (!sendOk) {
            if (callback != null) callback.onResult(false, "命令发送失败", null);
            return;
        }
        final Handler handler = new Handler(android.os.Looper.getMainLooper());
        SerialPortService.OnSerialDataListener listener = new SerialPortService.OnSerialDataListener() {
            @Override
            public void onDataReceived(String port, String hexData, ProtocolResult result) {
                if (result != null && result.statusType == SerialProtocolUtil.STATUS_READ_SENSOR) {
                    removeDataListener(this);
                    handler.removeCallbacksAndMessages(null);
                    if (callback != null) callback.onResult(true, "设备返回成功", result);
                }
            }
        };
        addDataListener(listener);
        handler.postDelayed(() -> {
            removeDataListener(listener);
            if (callback != null) callback.onResult(false, "设备无响应超时", null);
        }, TIME_OUT_MILLIS);
    }

    /**
     * 发送写配置参数命令并等待响应
     */
    public void sendWriteConfigWithResult(int configType, String data, CommandCallback callback) {
        boolean sendOk = sendWriteConfig(configType, data);
        if (!sendOk) {
            if (callback != null) callback.onResult(false, "命令发送失败", null);
            return;
        }
        final Handler handler = new Handler(android.os.Looper.getMainLooper());
        SerialPortService.OnSerialDataListener listener = new SerialPortService.OnSerialDataListener() {
            @Override
            public void onDataReceived(String port, String hexData, ProtocolResult result) {
                if (result != null && result.statusType == SerialProtocolUtil.STATUS_WRITE_CONFIG) {
                    removeDataListener(this);
                    handler.removeCallbacksAndMessages(null);
                    if (callback != null) callback.onResult(true, "设备返回成功", result);
                }
            }
        };
        addDataListener(listener);
        handler.postDelayed(() -> {
            removeDataListener(listener);
            if (callback != null) callback.onResult(false, "设备无响应超时", null);
        }, TIME_OUT_MILLIS);
    }

    /**
     * 发送读配置参数命令并等待响应
     */
    public void sendReadConfigWithResult(int configType, CommandCallback callback) {
        boolean sendOk = sendReadConfig(configType);
        if (!sendOk) {
            if (callback != null) callback.onResult(false, "命令发送失败", null);
            return;
        }
        final Handler handler = new Handler(android.os.Looper.getMainLooper());
        SerialPortService.OnSerialDataListener listener = new SerialPortService.OnSerialDataListener() {
            @Override
            public void onDataReceived(String port, String hexData, ProtocolResult result) {
                if (result != null && result.statusType == SerialProtocolUtil.STATUS_READ_CONFIG) {
                    removeDataListener(this);
                    handler.removeCallbacksAndMessages(null);
                    if (callback != null) callback.onResult(true, "设备返回成功", result);
                }
            }
        };
        addDataListener(listener);
        handler.postDelayed(() -> {
            removeDataListener(listener);
            if (callback != null) callback.onResult(false, "设备无响应超时", null);
        }, TIME_OUT_MILLIS);
    }

    /**
     * 发送错误恢复命令并等待响应
     */
    public void sendErrorRecoveryWithResult(int errorType, CommandCallback callback) {
        boolean sendOk = sendErrorRecovery(errorType);
        if (!sendOk) {
            if (callback != null) callback.onResult(false, "命令发送失败", null);
            return;
        }
        final Handler handler = new Handler(android.os.Looper.getMainLooper());
        SerialPortService.OnSerialDataListener listener = new SerialPortService.OnSerialDataListener() {
            @Override
            public void onDataReceived(String port, String hexData, ProtocolResult result) {
                if (result != null && result.statusType == SerialProtocolUtil.STATUS_ERROR_RECOVERY) {
                    removeDataListener(this);
                    handler.removeCallbacksAndMessages(null);
                    if (callback != null) callback.onResult(true, "设备返回成功", result);
                }
            }
        };
        addDataListener(listener);
        handler.postDelayed(() -> {
            removeDataListener(listener);
            if (callback != null) callback.onResult(false, "设备无响应超时", null);
        }, TIME_OUT_MILLIS);
    }
} 